#!/usr/bin/env -S node  # 执行及构建入口
const $ = globalThis.$ = new Proxy({},{
	get(m,k){
		let U=undefined; if(m[k]!==U) return m[k];
		let n = k.replace(/^_+/,'').split('_')[0];
		if(m[n]!==U) return U;  let v=UIX.auto(n);
		if(!v) return U; let T=v.tar, A=!T||T.run;
		if(T?.run && T.run!==true) require(T.run);
		if(A){ require(v.src); return m[k]; }
		let tar='usable.tar: '+Object.keys(T);
		$.err(`$.${k}.disable`, tar, {fix:1});
	},
});

// require代码: ESM转CJS(有限支持)
const $M=require('module'), RAW=$M.prototype._compile;
const INC = /import(\s+\S+\s+)from(\s+['"]\S+?["'])/g;
const RE = (x,k,v)=>`const ${k}= require(${v})`;
const EXPORT = /(^|\n)export\s+default\s+/g;
$M.prototype._compile = function(v,p){
	v = v.replace(EXPORT, '$1module.exports=');
	return RAW.call(this, v.replace(INC,RE), p);
};

// TODO: 执行 ...
global.GEN = {RUN:true};

// TODO: 内部 ...
const UIX = global.UIX = {
	ROOT: __dirname.replace(/\\/g,'/')+'/',
	/**
	 * 取得$[k]信息
	 * @param k string 方法名  $[k]
	 * @param txt boolean 是否需要代码  返回含:txt
	 * @return Promise|json|mill  Promise:txt=true
	 * 		返回JSON: {via, src, fix, tar, ?txt}
	 */
	auto(k, txt=false){
		const $FS=require('fs'), DIR=UIX.ROOT+'/@script/';
		const RD=/^[a-z][a-z\d]+$/, RF=/^[a-z][a-z\d]+\.js$/;
		const OPT={withFileTypes:true}, M={};
		const TAR=require(DIR+'/.tar.js'), MAP=p=>{
			$FS.readdirSync(DIR+p,OPT).forEach(v=>{
				let isDir=v.isDirectory(), n=v.name, m=p+n;
				if(isDir) return RD.test(n) && MAP(m+'/');
				if(m.indexOf('/')<0 || !RF.test(n)) return;
				let via=m.slice(0,-3), k=via, src=DIR+m;
				if(k.slice(-4)==='/aac') k = k.slice(0, -4);
				else if(k.slice(0,4)==='aac/') k=k.slice(4);
				k=k.replace(/\/(.)/g,(x,a)=>a.toUpperCase());
				M[k] = {via, src, fix:[src,1,1], tar:TAR[k]};
			});
		};
		const TXT = async function(k){
			let m=M[k];  if(!m) return null;  let v=m.txt;
			if(v) return (v instanceof Promise) ? v : m;
			return m.txt=$.fsRead(m.src).then(v=>m.txt=v);
		};
		UIX.auto = function(k, txt=false){
			return txt ? TXT(k) : (M[k]||null);
		};
		MAP('');  return UIX.auto(k,txt);
	},
};

module.exports = $;
